/*
* ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
* Without permission, no one has the right to obtain, disclose or use this software in any way.
*/

package ecarx.xsf.notificationcenter;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;

import ecarx.eas.notification.InitCallback;
import ecarx.xsf.notificationcenter.common.Constants;
import ecarx.xsf.notificationcenter.notification.ILauncherControllerService;
import ecarx.xsf.notificationcenter.notification.INotificationService;
import ecarx.xsf.notificationcenter.scenecard.ISceneCardService;

/**
 * FileName: BaseServiceConnection.java <br>
 * Description : 连接服务端业务实现 <br>
 * Create Time: 2019/12/25 17:17<br>
 * Update Time: 2021/8/3 14:07 <br>
 *
 * @since 1.0.0
 */
public class BaseServiceConnection {

    private static final String TAG = "BaseServiceConnection";
    private static final String SERVICE_PACKAGE_NAME = "ecarx.xsf.notificationcenter";
    private static final String ACTION_NOTIFICATION_SERVICE = "android.intent.action.NOTIFICATION_PROXY_SERVICE";
    private static final String ACTION_SCENE_CARD_SERVICE = "android.intent.action.SCENE_CARD_PROXY_SERVICE";
    private static final String ACTION_MASCOT_CARD_SERVICE = "android.intent.action.LAUNCHER_CONTROLLER_PROXY_SERVICE";

    Context mContext;
    InitCallback mCallback;
    private boolean bindSuccess;

    private final LauncherControllerApi api;
    private final String mApiName;

    public BaseServiceConnection(Context context, LauncherControllerApi api, String apiName, InitCallback callback) {
        this.mContext = context;
        this.mApiName = apiName;
        this.api = api;
        mCallback = callback;
    }

    ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(TAG, "onServiceConnected: " + name);

            if (Constants.IAPINAME.NOTIFICATION_API.equals(mApiName)) {
                final INotificationService iNotificationService = INotificationService.Stub.asInterface(service);
                try {
                    iNotificationService.asBinder().linkToDeath(mDeathRecipient, 0);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                api.setNotificationService(iNotificationService);
            } else if (Constants.IAPINAME.MASCOT_API.equals(mApiName)) {
                final ILauncherControllerService iLauncherControllerService = ILauncherControllerService.Stub.asInterface(service);
                try {
                    iLauncherControllerService.asBinder().linkToDeath(mDeathRecipient, 0);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                api.setMascotCardService(iLauncherControllerService);
            } else if (Constants.IAPINAME.SCENE_CARD_API.equals(mApiName)) {
                final ISceneCardService iSceneCardService = ISceneCardService.Stub.asInterface(service);
                try {
                    iSceneCardService.asBinder().linkToDeath(mDeathRecipient, 0);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                api.setSceneCardService(iSceneCardService);
            }

            if (mCallback != null) {
                mCallback.onInit(true, mApiName);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected() called with: name = [" + name + "]");
            bindSuccess = false;
        }

        @Override
        public void onBindingDied(ComponentName name) {
            Log.e(TAG, "onBindingDied() called with: name = [" + name + "]");
            bindSuccess = false;
            reconnectService();
        }
    };
    IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            bindSuccess = false;
            reconnectService();
        }
    };


    /**
     * * 服务重连
     *
     * @since 1.0.0
     */
    private void reconnectService() {
        if (Constants.IAPINAME.NOTIFICATION_API.equals(mApiName)) {
            checkNotificationService();
        } else if (Constants.IAPINAME.MASCOT_API.equals(mApiName)) {
            checkMascotService();
        } else if (Constants.IAPINAME.SCENE_CARD_API.equals(mApiName)) {
            checkSceneCardService();
        }
    }

    /**
     * * 检查智能卡片服务连接状态.
     *
     * @since 1.0.0
     */
    private void checkSceneCardService() {
        if (api.getSceneCardService() == null) {
            connectService();
            return;
        }
        Log.i(TAG, "scene card binder died");
        api.getSceneCardService().asBinder().unlinkToDeath(mDeathRecipient, 0);
        api.setSceneCardService(null);
        connectService();
    }

    /**
     * * 检查形象提示服务连接状态.
     *
     * @since 1.0.0
     */
    private void checkMascotService() {
        if (api.getMascotService() == null) {
            connectService();
            return;
        }

        Log.i(TAG, "mascot binder died");
        api.getMascotService().asBinder().unlinkToDeath(mDeathRecipient, 0);
        api.setMascotCardService(null);
        connectService();
    }

    /**
     * * 检查通知中心服务连接状态.
     *
     * @since 1.0.0
     */
    private void checkNotificationService() {
        if (api.getNotificationService() == null) {
            connectService();
            return;
        }
        Log.i(TAG, "notification binder died");
        api.getNotificationService().asBinder().unlinkToDeath(mDeathRecipient, 0);
        api.setNotificationService(null);
        connectService();
    }

    /**
     * 服务连接.
     *
     * @since 1.0.0
     * 根据 API 名称选择连接服务类型
     */
    void connectService() {
        Log.i(TAG, "connectService " + mApiName);
        if (!TextUtils.isEmpty(mApiName)) {
            Intent intent = new Intent();
            intent.setPackage(SERVICE_PACKAGE_NAME);
            if (Constants.IAPINAME.NOTIFICATION_API.equals(mApiName)) {
                intent.setAction(ACTION_NOTIFICATION_SERVICE);
            } else if (Constants.IAPINAME.MASCOT_API.equals(mApiName)) {
                intent.setAction(ACTION_MASCOT_CARD_SERVICE);
            } else if (Constants.IAPINAME.SCENE_CARD_API.equals(mApiName)) {
                intent.setAction(ACTION_SCENE_CARD_SERVICE);
            }
            if (!TextUtils.isEmpty(intent.getAction())) {
                bindSuccess = mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
            } else {
                Log.e(TAG, "api name error " + mApiName);
            }
        } else {
            Log.e(TAG, "api is null");
        }
    }

    public boolean isBindSuccess() {
        return bindSuccess;
    }

    /**
     * 释放链路
     */
    public void release() {
        if (Constants.IAPINAME.NOTIFICATION_API.equals(mApiName)) {
            if (mContext == null || api.getNotificationService() == null) {
                logConnectError();
                return;
            }
            Log.i(TAG, "release Notification API connection");
            api.getNotificationService().asBinder().unlinkToDeath(mDeathRecipient, 0);
            api.setNotificationService(null);
            if (mConnection != null) {
                mContext.unbindService(mConnection);
            }
        } else if (Constants.IAPINAME.MASCOT_API.equals(mApiName)) {
            if (mContext == null || api.getMascotService() == null) {
                logConnectError();
                return;
            }
            Log.i(TAG, "release mascot card API connection");
            api.getMascotService().asBinder().unlinkToDeath(mDeathRecipient, 0);
            api.setMascotCardService(null);
            if (mConnection != null) {
                mContext.unbindService(mConnection);
            }
        } else if (Constants.IAPINAME.SCENE_CARD_API.equals(mApiName)) {
            if (mContext == null || api.getSceneCardService() == null) {
                logConnectError();
                return;
            }
            Log.i(TAG, "release scene card API connection");
            api.getSceneCardService().asBinder().unlinkToDeath(mDeathRecipient, 0);
            api.setSceneCardService(null);
            if (mConnection != null) {
                mContext.unbindService(mConnection);
            }
        }

    }

    private void logConnectError() {
        Log.e(TAG, "service is null");
    }
}
